/***************************************************************************\
 * Copyright (C) by Keio University
 * main.cpp created in 01 2012.
 * Mail : fdesorbi@hvrl.ics.keio.ac.jp
 *
 * main.cpp is part of the HVRL Engine Library.
 *
 * The HVRL Engine Library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * The HVRL Engine Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 \***************************************************************************/

#include <GL/freeglut.h>
#include <opencv2/opencv.hpp>

#include <hvrl/common/Common.hpp>

#include <cuda.h>
#include <cuda_runtime.h>

#include <hvrl/gpgpu/cuda/BilateralFilterTemplate.cuh>

using namespace hvrl;
using namespace cuda;


int
main(int argc, char **argv)
{
  if (argc == 1)
    {
      hvrl::Log::add().error("main", "filename argument is missing");
      return 1;
    }

  // Load grayscale image
  cv::Mat myimage = cv::imread(argv[1], 0);

  cv::imwrite("input.png", myimage);
  if (myimage.data == 0)
    {
      hvrl::Log::add().error("main", "input file is incorrect");
      return 1;
    }

  cv::Mat myimage_res(myimage.size(), myimage.type());


  BilateralFiltering_CU<unsigned char> bf;
  bf.initialize(40.0f, 10.0f, 5);

  if (myimage.channels() == 1)
    {

	  unsigned char * input = 0;
	  unsigned char * output = 0;
      cudaMalloc((void**)&input, myimage.cols* myimage.rows * sizeof(unsigned char));
      cudaMemcpy(input, myimage.data, myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyHostToDevice);
      cudaMalloc((void**)&output, myimage.cols* myimage.rows * sizeof(unsigned char));

      if(bf.apply(input, output, myimage.cols, myimage.rows,16,16)==false){
    	  std::cerr << "Unable to apply the filter" << std::endl;
      }

      cudaMemcpy(myimage_res.data, output, myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyDeviceToHost);
      cudaFree(input);
      cudaFree(output);
    }


  cv::imwrite("output.png", myimage_res);

  return 0;

  /*cv::Mat myimage_res(myimage.size(), myimage.type());
  hvrl::cuda::BilateralFilter::setKernel(18.0f, 0.1f, 5);

  unsigned char * input = 0;
  unsigned char * output = 0;

  if (myimage.channels() == 1)
    {
      cudaMalloc((void**)&input, myimage.cols* myimage.rows * sizeof(unsigned char));
      cudaMemcpy(input, myimage.data, myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyHostToDevice);
      cudaMalloc((void**)&output, myimage.cols* myimage.rows * sizeof(unsigned char));

      hvrl::cuda::BilateralFilter::computeC1(input, output, myimage.cols,
          myimage.rows);

      cudaMemcpy(myimage_res.data, output, myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyDeviceToHost);
      cudaFree(input);
      cudaFree(output);
    }
  else
    {
      if (myimage.channels() == 3)
        {
          cudaMalloc((void**)&input,3 * myimage.cols* myimage.rows * sizeof(unsigned char));
          cudaMemcpy(input, myimage.data, 3 * myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyHostToDevice);
          cudaMalloc((void**)&output,3 * myimage.cols* myimage.rows * sizeof(unsigned char));

          hvrl::cuda::BilateralFilter::computeC3(input, output, myimage.cols,
              myimage.rows);

          cudaMemcpy(myimage_res.data, output, 3 * myimage.cols* myimage.rows * sizeof(unsigned char), cudaMemcpyDeviceToHost);
          cudaFree(input);
          cudaFree(output);
        }
    }

  cv::imwrite("output.png", myimage_res);

  cudaFree(input);
  cudaFree(output);

  return 0;*/
}

